#include "Graph.h"
#include "StringToIdMatcher.h"
#include "util/ByIdMatcher.h"

Graph::Graph() {
	this->tempNumber = 0;
}

Graph::~Graph() {
	while (!(this->edges.isEmpty())) {
		delete (this->edges.removeFirst());
	}
	while (!(this->vertices.isEmpty())) {
		delete (this->vertices.removeFirst());
	}
}

Vertex* Graph::addVertex(string id) throw (DuplicateElementException) {
	Vertex* vertex = new Vertex(id);
	ByIdMatcher<Vertex> matcher(vertex);
	if (!(this->vertices.contains(&matcher))) {
		this->vertices.append(vertex);
		return vertex;
	} else {
		delete vertex;
		throw(DuplicateElementException("El vertice \"" + id + "\" ya existe en el grafo."));
	}
}

Edge* Graph::addEdge(string id, Vertex* origin, Vertex* destination,
		double distanceInMeters, double speedInKMH)
		throw (DuplicateElementException) {
	StringToIdMatcher<Edge> matcher(id);
	if (!(this->edges.contains(&matcher))) {
		Edge* edge = new Edge(id, origin, destination,
				distanceInMeters, speedInKMH);
		this->edges.append(edge);
		return edge;
	} else {
		throw(DuplicateElementException("La arista \"" + id
				+ "\" ya existe en el grafo."));
	}
}

path::Path* Graph::solvePath(path::PathSolverAlgorithm &solver, Vertex* origin,
		Vertex* destination) throw (OutOfReachException) {
	return solver.solvePath(origin, destination, &this->vertices, &this->edges);
}

Vertex* Graph::getVertex(string id) throw (util::ElementNotFoundException) {
	StringToIdMatcher<Vertex> matcher(id);
	try {
		return this->vertices.search(&matcher);
	} catch (util::ElementNotFoundException e) {
		throw(util::ElementNotFoundException("El vertice \"" + id
				+ "\" no se encuentra en el grafo."));
	}
}

Edge* Graph::getEdge(string id) throw (util::ElementNotFoundException) {
	StringToIdMatcher<Edge> matcher(id);
	return this->edges.search(&matcher);
}

void Graph::visitVertices(GraphVisitor &aVisitor) {
	util::LinkedList<Vertex>::Iterator it = this->vertices.iterator();
	while (it.hasNext()) {
		aVisitor.visitVertex(it.next());
	}
}
void Graph::visitEdges(GraphVisitor &aVisitor) {
	util::LinkedList<Edge>::Iterator it = this->edges.iterator();
	while (it.hasNext()) {
		aVisitor.visitEdge(it.next());
	}
}

bool Graph::isEmpty() {
	return this->vertices.isEmpty();
}
